package dialer.ws.common.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRRtfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.export.JRXmlExporter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

import org.apache.log4j.Logger;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.authentication.encoding.PasswordEncoder;

/**
 * @author ediaz
 * 
 * 
 */
public class Util {

	/**
	 * 
	 * Mascara para formatos de fecha
	 */
	private final static String MASCARA_CORTO_FECHA = "yyyyMMdd";
	private final static String MASCARA_NORMAL_FECHA = "yyyyMMddHHmmss";

	protected static Logger log = Logger.getLogger(FacesUtils.class);

	/**
	 * 
	 * Se utiliza las constantes para mascaras de fechas
	 * 
	 * @param date
	 * @return
	 */
	public static String formatoCortoDateToString(Date date) {
		SimpleDateFormat formato = new SimpleDateFormat(MASCARA_CORTO_FECHA);
		return formato.format(date);
	}

	/**
	 * 
	 * Se utiliza las constantes para mascaras de fechas
	 * 
	 * @param date
	 * @return
	 */
	public static String formatDateToString(Date date) {
		SimpleDateFormat formato = new SimpleDateFormat(MASCARA_NORMAL_FECHA);
		return formato.format(date);
	}

	public static String encodePassword(String pass) {
		PasswordEncoder encoder = new Md5PasswordEncoder();
		String hashedPass = encoder.encodePassword(pass, null);
		return hashedPass;
	}

	public static void print(String resource, String filename, String format, Map<?, ?> params, List<?> lista) {
		InputStream fileStream = getDocumentStream(resource);
		JasperDesign jasperDesign = null;
		jasperDesign = loadJRXml(fileStream);
		JasperReport jasperReport = null;
		jasperReport = compileReport(jasperDesign);
		JasperPrint jasperPrint = null;
		jasperPrint = fillReport(jasperReport, params, lista);

		byte[] output = null;
		JRExporter exporter = null;
		if (format.equals("FORMAT_PDF")) {
			FacesUtils.getResponse().setContentType("application/pdf");
			FacesUtils.getResponse().setHeader("Content-Disposition", "inline;filename=\"" + filename + "\"");
			exporter = new JRPdfExporter();
		} else if (format.equals("FORMAT_CSV")) {
			FacesUtils.getResponse().setContentType("text/plain");
			exporter = new JRCsvExporter();
		} else if (format.equals("FORMAT_HTML")) {
			FacesUtils.getResponse().setContentType("text/html");
		} else if (format.equals("FORMAT_XLS")) {
			FacesUtils.getResponse().setContentType("application/vnd.ms-excel");
			FacesUtils.getResponse().setHeader("Content-Disposition", "inline;filename=\"" + filename + "\"");
			FacesUtils.getResponse().setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
			exporter = new JRXlsExporter();
		} else if (format.equals("FORMAT_XMl")) {
			FacesUtils.getResponse().setContentType("text/xml");
			exporter = new JRXmlExporter();
		} else if (format.equals("FORMAT_RTF")) {
			FacesUtils.getResponse().setContentType("application/rtf");
			exporter = new JRRtfExporter();
		}

		output = exportReportToBytes(jasperPrint, exporter, filename, format);
		FacesUtils.getResponse().setContentLength(output.length);
		writeReport(output);
		FacesContext.getCurrentInstance().responseComplete();
	}

	public static InputStream getDocumentStream(String path) {
		InputStream reportInstream = null;
		reportInstream = Util.class.getClassLoader().getResourceAsStream(path);
		return reportInstream;
	}

	public static JasperDesign loadJRXml(InputStream fileStream) {
		JasperDesign jasperDesign = null;
		try {
			jasperDesign = JRXmlLoader.load(fileStream);
		} catch (JRException e) {
			log.error(e.getMessage());
		}
		return jasperDesign;
	}

	public static JasperReport compileReport(JasperDesign jasperDesign) {
		JasperReport jasperReport = null;
		try {
			jasperReport = JasperCompileManager.compileReport(jasperDesign);
		} catch (JRException e) {
			log.error(e.getMessage());
		}
		return jasperReport;
	}

	public static JasperPrint fillReport(JasperReport jasperReport, Map<?, ?> params, Collection<?> printList) {
		JasperPrint jasperPrint = null;
		JRDataSource jrDataSource = new JRBeanCollectionDataSource(printList);
		try {
			jasperPrint = JasperFillManager.fillReport(jasperReport, params, jrDataSource);
		} catch (JRException e) {
			log.error(e.getMessage());
		}
		return jasperPrint;
	}

	public static byte[] exportReportToBytes(JasperPrint jasperPrint, JRExporter exporter, String filename,
			String format) {
		byte[] output;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
		try {
			exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, FacesUtils.getResponse().getOutputStream());
		} catch (IOException e) {
			log.error(e.getMessage());
		}
		exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, filename);
		if (format.equals("FORMAT_XMl")) {
			exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
			exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
		}

		try {
			exporter.exportReport();
		} catch (JRException e) {
			log.error(e.getMessage());
		}
		output = baos.toByteArray();
		return output;
	}

	private static void writeReport(byte[] output) {
		ServletOutputStream outputStream = null;
		try {
			outputStream = FacesUtils.getResponse().getOutputStream();
			outputStream.write(output);
			outputStream.flush();
		} catch (IOException e) {
			log.error("Error writing report output", e);
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (IOException e) {
				log.error("Error closing report output stream", e);
			}
		}
	}
}
